﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace XuanFe.AppLaunch.Common.Security
{
    /// <summary>
    /// 加解密工具帮手类
    /// </summary>
    internal class CryptographyHelper
    {
        private static CryptographyHelper instance = new CryptographyHelper();

        public static CryptographyHelper Instance
        {
            get
            {
                return instance;
            }
        }

        /// <summary>
        /// 十六进制字符串转换为字节数组
        /// </summary>
        /// <param name="s">十六进制字符串</param>
        /// <returns>字节数组</returns>
        public byte[] StrToBytes(string s)
        {
            int length = s.Length / 2;
            byte[] bytes = new byte[length];
            for (int i = 0; i < length; i++)
            {
                bytes[i] = Convert.ToByte(s.Substring(i * 2, 2), 16);
            }

            return bytes;
        }
        /// <summary>
        /// 字节数组转换为十六进制字符串
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>十六进制字符串</returns>
        public string BytesToStr(byte[] bytes)
        {
            StringBuilder sbResult = new StringBuilder();
            foreach (byte b in bytes)
            {
                sbResult.AppendFormat("{0:x2}", b);
            }
            return sbResult.ToString();
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="text">明文</param>
        /// <returns></returns>
        public string MD5(string text)
        {
            return MD5(Encoding.GetEncoding("gb2312").GetBytes(text));
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="text">明文</param>
        /// <returns></returns>
        public string MD5(byte[] text)
        {
            return BytesToStr(MD5ToBytes(text)).ToUpper();
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="text">明文</param>
        /// <returns></returns>
        public byte[] MD5ToBytes(string text)
        {
            return MD5ToBytes(Encoding.GetEncoding("gb2312").GetBytes(text));
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="text">明文</param>
        /// <returns></returns>
        public byte[] MD5ToBytes(byte[] text)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            return md5.ComputeHash(text);
        }
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="text">明文</param>
        /// <returns>密文</returns>
        public string DESEncryptor(string key, string text)
        {
            try
            {
                byte[] keys = new MD5CryptoServiceProvider().ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(key));
                byte[] rgbKey = new byte[8];
                byte[] rgbIV = new byte[8];
                Array.Copy(keys, 0, rgbKey, 0, 8);
                Array.Copy(keys, 8, rgbIV, 0, 8);
                byte[] inputByteArray = Encoding.GetEncoding("gb2312").GetBytes(text);
                DESCryptoServiceProvider csp = new DESCryptoServiceProvider();
                csp.GenerateKey();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, csp.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return BytesToStr(mStream.ToArray()).ToUpper();
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="text">密文</param>
        /// <returns>明文</returns>
        public string DESDecryptor(string key, string text)
        {
            try
            {
                if (text.Length % 2 != 0) return string.Empty;

                byte[] keys = new MD5CryptoServiceProvider().ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(key));
                byte[] rgbKey = new byte[8];
                byte[] rgbIV = new byte[8];
                Array.Copy(keys, 0, rgbKey, 0, 8);
                Array.Copy(keys, 8, rgbIV, 0, 8);
                byte[] inputByteArray = StrToBytes(text);
                DESCryptoServiceProvider csp = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, csp.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Encoding.GetEncoding("gb2312").GetString(mStream.ToArray());
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 3DES加密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="text">明文</param>
        /// <returns>密文</returns>
        public string TripleDESEncryptor(string key, string text)
        {
            try
            {
                byte[] inputByteArray = Encoding.GetEncoding("gb2312").GetBytes(text);
                TripleDESCryptoServiceProvider csp = new TripleDESCryptoServiceProvider();
                csp.Key = new MD5CryptoServiceProvider().ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(key));
                csp.Mode = CipherMode.ECB;
                csp.Padding = PaddingMode.PKCS7;
                ICryptoTransform Encryptor = csp.CreateEncryptor();
                return BytesToStr(Encryptor.TransformFinalBlock(inputByteArray, 0, inputByteArray.Length)).ToUpper();
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 3DES解密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="text">密文</param>
        /// <returns>明文</returns>
        public string TripleDESDecryptor(string key, string text)
        {
            try
            {
                if (text.Length % 2 != 0) return string.Empty;

                byte[] inputByteArray = StrToBytes(text);
                TripleDESCryptoServiceProvider csp = new TripleDESCryptoServiceProvider();
                csp.Key = new MD5CryptoServiceProvider().ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(key));
                csp.Mode = CipherMode.ECB;
                csp.Padding = PaddingMode.PKCS7;
                ICryptoTransform Encryptor = csp.CreateDecryptor();
                return Encoding.GetEncoding("gb2312").GetString(Encryptor.TransformFinalBlock(inputByteArray, 0, inputByteArray.Length));
            }
            catch
            {
                return string.Empty;
            }
        }
    }
}